home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume16 / ichk / patch1 < prev    next >
Encoding:
Internet Message Format  |  1991-02-05  |  16.9 KB

  1. From: jgd@Dixie.Com (John G. DeArmond)
  2. Newsgroups: comp.sources.misc
  3. Subject: v16i092:  Ichk - The inode/filesystem checker (Fixed), Patch1
  4. Message-ID: <1991Feb3.213938.186@sparky.IMD.Sterling.COM>
  5. Date: 3 Feb 91 21:39:38 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7. X-Checksum-Snefru: eccb4c41 c3bb6bed df7d534a c1c7d9ab
  8.  
  9. Submitted-by: jgd@Dixie.Com (John G. DeArmond)
  10. Posting-number: Volume 16, Issue 92
  11. Archive-name: ichk/patch1
  12. Patch-To: ichk: Volume 16, Issue 75
  13.  
  14. Oops!
  15.  
  16. Someone pointed out that the posted version of Ichk I placed in 
  17. comp.sources.misc and alt.sources contained a fatal bug.  Mea Culpa :-(
  18. I'm so embarrassed!  Enclosed is a revised version of Ichk that does
  19. something other than eat CPU time.  Please replace the version of
  20. Ichk.c in your archive with this version.  I have also included a duplicate
  21. copy of the instruction file, Ichk.txt.
  22.  
  23. John
  24.  
  25. ------------------------------ cut here -------------------------------------
  26. #!/bin/sh
  27. # This is a shell archive (shar 3.11)
  28. # made 02/01/1991 09:07 UTC by jgd@rsiatl
  29. # Source directory /usr/local/tools/ichk
  30. #
  31. # existing files WILL be overwritten
  32. #
  33. # This shar contains:
  34. # length  mode       name
  35. # ------ ---------- ------------------------------------------
  36. #    405 -rw-r--r-- README
  37. #   6095 -r--r--r-- ichk.c
  38. #   7310 -rw-rw---- ichk.txt
  39. #
  40. touch 2>&1 | fgrep '[-amc]' > /tmp/s3_touch$$
  41. if [ -s /tmp/s3_touch$$ ]
  42. then
  43.     TOUCH=can
  44. else
  45.     TOUCH=cannot
  46. fi
  47. rm -f /tmp/s3_touch$$
  48. # ============= README ==============
  49. echo "x - extracting README (Text)"
  50. sed 's/^X//' << 'SHAR_EOF' > README &&
  51. XOops!
  52. X
  53. XSomeone pointed out that the posted version of Ichk I placed in 
  54. Xcomp.sources.misc and alt.sources contained a fatal bug.  Mea Culpa :-(
  55. XI'm so embarrassed!  Enclosed is a revised version of Ichk that does
  56. Xsomething other than eating CPU time.  Please replace the version of
  57. XIchk.c in your archive with this version.  I have also included a duplicate
  58. Xcopy of the instruction file, Ichk.txt.
  59. X
  60. XJohn
  61. X
  62. SHAR_EOF
  63. chmod 0644 README || echo "restore of README fails"
  64. if [ $TOUCH = can ]
  65. then
  66.     touch -am 0201040691 README
  67. fi
  68. set `wc -c README`;Wc_c=$1
  69. if test "$Wc_c" != "405"
  70. then echo original size 405, current size $Wc_c;fi
  71. # ============= ichk.c ==============
  72. echo "x - extracting ichk.c (Text)"
  73. sed 's/^X//' << 'SHAR_EOF' > ichk.c &&
  74. X
  75. X#ifdef SCCSID
  76. Xstatic sccsid[] = "@(#) ichk.c 1.5 91/02/01  04:01:47";  
  77. X#endif
  78. X
  79. X#include <stdio.h>
  80. X#include <sys/types.h>
  81. X#include <sys/statfs.h>
  82. X#include <sys/signal.h>
  83. X
  84. X/* this program checks vital parameters on the file system it is invoked
  85. X** against and when a problem is found, runs a specified program that
  86. X** remedies the problem (hopefully).
  87. X**
  88. X** This program must be setuid root and/or run from root 
  89. X*/
  90. X
  91. Xstruct statfs buf;
  92. Xlong inode_trigger = 200L;
  93. Xlong block_trigger = 1000L;
  94. Xlong ratio = 5L;
  95. Xint i;
  96. Xchar file_sys[256];
  97. Xchar action[256];
  98. Xchar c;
  99. Xint verbose=0;
  100. Xint snooze=10;
  101. Xlong i_ratio;
  102. Xint talk=0;
  103. X
  104. Xextern int optind;
  105. Xextern char *optarg;
  106. Xextern int errno;
  107. Xextern void usage();
  108. Xextern void take_action();
  109. Xextern char *decimalize();
  110. Xextern void terminator();
  111. X
  112. Xmain(argc,argv)
  113. Xint argc;
  114. Xchar **argv;
  115. X{
  116. X
  117. X#ifdef DAEMON
  118. X    /* do NOT do this if you run ichk from init.  Init gets real pissed */
  119. X    /* with processes that try to daemonize themselves */
  120. X    if (fork())
  121. X        exit(0);
  122. X#endif
  123. X
  124. X    setpgrp();    /* make us a little bit independent */
  125. X
  126. X
  127. X    signal(SIGTERM,terminator);
  128. X    signal(SIGINT,terminator);
  129. X    signal(SIGHUP,terminator);
  130. X
  131. X    action[0] = '\0';
  132. X
  133. X    if (argc < 2) {
  134. X        usage();
  135. X    }
  136. X
  137. X    if ( setuid(0) ) {
  138. X        fprintf(stderr,"*** ERROR: Setuid root failed");
  139. X        sleep(5);
  140. X        exit(2);
  141. X    }            
  142. X    
  143. X    if ( setgid(0) ) {
  144. X        fprintf(stderr,"*** ERROR: Setgid root failed");
  145. X        sleep(5);
  146. X        exit(3);
  147. X    }            
  148. X
  149. X    while ( (c =  getopt(argc, argv, "a:b:i:r:s:vt")) != -1 ) {
  150. X        switch (c) {
  151. X            case 'a':    /* specifies the action to take */
  152. X                strcpy(action,optarg);
  153. X                break;
  154. X            case 'b':    /* low block count threshold */
  155. X                block_trigger = atol(optarg);
  156. X                if (block_trigger == 0L)
  157. X                    usage();
  158. X                break;
  159. X            case 'i':
  160. X                inode_trigger=atol(optarg);
  161. X                if (inode_trigger == 0L)
  162. X                    usage();
  163. X                break;
  164. X            case 'r':
  165. X                ratio=atol(optarg);
  166. X                if (ratio == 0L) 
  167. X                    usage();
  168. X                break;
  169. X            case 'v':
  170. X                verbose=1;
  171. X                break;
  172. X            case 's':
  173. X                snooze = atoi(optarg);
  174. X                if (snooze == 0 ) 
  175. X                    usage();
  176. X                break;
  177. X            case 't':    /* give a report only or (t)alk */
  178. X                talk=1;
  179. X                break;
  180. X            case '?':
  181. X                usage();
  182. X                break;
  183. X        }
  184. X    }
  185. X    if (talk) verbose = 0;
  186. X
  187. X    strcpy(file_sys,argv[optind]);
  188. X
  189. X    if (verbose)
  190. X        printf("pid = %d\n", getpid());
  191. X
  192. X    errno=0;
  193. X    if ( statfs(file_sys, &buf, sizeof(struct statfs), 0) == -1) {
  194. X        fprintf(stderr,"*** ERROR: statfs() failed, errno = %d\n",errno);
  195. X        fprintf(stderr,"file_sys = <%s>\n", file_sys);
  196. X        fprintf(stderr,"sizeof(struct statfs) = %d \n", sizeof(struct statfs));
  197. X        sleep(10); /* keeps init happy */
  198. X        exit(4);
  199. X    }
  200. X
  201. X    if (talk) {
  202. X        printf("%s %ld %ld ", buf.f_fname, buf.f_blocks, buf.f_bfree);
  203. X        printf("%ld %ld %s\n", buf.f_files, buf.f_ffree, 
  204. X            decimalize((buf.f_bfree*10L) / (buf.f_ffree))); 
  205. X        exit(0);
  206. X
  207. X    }
  208. X
  209. X
  210. X    if (verbose) {
  211. X        printf("File system type =    %d\n", buf.f_fstyp);
  212. X        printf("Total blocks =        %ld\n", buf.f_blocks);
  213. X        printf("Free blocks =         %ld\n", buf.f_bfree);
  214. X        printf("Total inodes =        %ld\n", buf.f_files);
  215. X        printf("Free inodes =         %ld\n", buf.f_ffree);
  216. X        printf("Volume name =         %s\n", buf.f_fname);
  217. X    }
  218. X
  219. X    while (1) {
  220. X
  221. X        if (statfs(file_sys, &buf, sizeof(struct statfs), 0) == -1) {
  222. X            /* maybe the problem will go away, nothing to do anyway*/
  223. X            sleep(10);    
  224. X            continue;
  225. X        }
  226. X
  227. X        i_ratio = (buf.f_bfree*10L) / buf.f_ffree;  
  228. X        /* preserving one decimal place of rounding */
  229. X
  230. X        /* ratio of blocks to inodes will go UP when the system starts losing
  231. X            inodes */
  232. X        if ( i_ratio >= (ratio*10L) ) {
  233. X            if (verbose)
  234. X                printf("Block to Inode ratio %s is too high\n", decimalize(i_ratio));
  235. X            take_action("ratio");
  236. X            goto slumber;
  237. X        } else {
  238. X            if (verbose)
  239. X                printf("Block to Inode ratio is %s\n", decimalize(i_ratio));
  240. X        }
  241. X
  242. X        if (buf.f_ffree < inode_trigger) {
  243. X            if (verbose)
  244. X                printf("Inodes low threshold triggered at %ld inodes\n", 
  245. X                    buf.f_ffree);
  246. X            take_action("inode");
  247. X            goto slumber;
  248. X        } else {
  249. X            if (verbose)
  250. X                printf("Inodes = %ld\n", 
  251. X                    buf.f_ffree);
  252. X        }    
  253. X
  254. X        if (buf.f_bfree < block_trigger) {
  255. X            if (verbose)
  256. X                printf("Blocks low threshold triggered at %ld blocks\n", 
  257. X                    buf.f_bfree);
  258. X            take_action("block");
  259. X            goto slumber;
  260. X        } else {
  261. X            if (verbose)
  262. X                printf("Blocks = %ld\n", 
  263. X                    buf.f_bfree);
  264. X        }    
  265. X
  266. X    slumber:
  267. X        sleep(snooze);
  268. X
  269. X    } /* for (;;) */
  270. X
  271. X    /* NOTREACHED */
  272. X    sleep(5);
  273. X    exit(0);
  274. X} /* main */
  275. X
  276. Xvoid
  277. Xtake_action(x)
  278. Xchar x[]; /* problem to be remedied */
  279. X{
  280. X    char buff[256];
  281. X
  282. X    if (!strlen(action)) 
  283. X        return;
  284. X
  285. X    sprintf(buff,"%s %s %s", action, file_sys, x);
  286. X    if (verbose)
  287. X        printf("Action taken:  Command line to system()\n\t%s\n",buff);
  288. X
  289. X    system(buff);
  290. X    return;
  291. X}
  292. X
  293. Xchar *
  294. Xdecimalize(x)
  295. Xlong x;
  296. X{
  297. X    static char buff[256];
  298. X    int len;
  299. X
  300. X    memset(buff,'\0',256);
  301. X
  302. X    sprintf(buff,"%ld", x);
  303. X    len = strlen(buff);
  304. X
  305. X    buff[len] = buff[len-1]; /* move last char over one to the right*/
  306. X    buff[len-1] = '.';
  307. X
  308. X    return(buff);
  309. X}
  310. X
  311. Xvoid
  312. Xusage()
  313. X{
  314. X
  315. X    fprintf(stderr,
  316. X    "\nUsage:\n\nichk <-a action>\n  <-i inode_trig>\n  <-r ratio>\n  <-v>\n");
  317. X    fprintf(stderr,
  318. X    "  <-s sleep_secs>\n  <-b block_count_trigger>\n  <-t>\n file_system_name\n");
  319. X    fprintf(stderr,
  320. X       "\nThe defaults are %ld inodes, %ld:1 block_to_inodes_ratio,\n", 
  321. X       inode_trigger, ratio);    
  322. X    fprintf(stderr,
  323. X       "%ld blocks, action = nothing and %d seconds between checks.\n", 
  324. X       block_trigger, snooze);
  325. X    fprintf(stderr,
  326. X        "\nWhen the <action> program is invoked, the program is passed the\n");
  327. X    fprintf(stderr,
  328. X    "following arguments:\nargv[1] == the file system\nargv[2] == the problem\n");
  329. X    fprintf(stderr,
  330. X    "\nargv[2] can be:\nratio      = ratio of blocks to inodes exceeded.\n");
  331. X    fprintf(stderr,
  332. X    "inode      = the low inode threshold exceeded.\n");
  333. X    fprintf(stderr,
  334. X    "block      = the low block threshold exceeded.\n");
  335. X    fprintf(stderr,
  336. X    "If the -t (talk) flag is specified, all other options are ignored and\n");
  337. X    fprintf(stderr,
  338. X    "ichk reports the status of the file system in the form:\n fs_name ");
  339. X    fprintf(stderr,
  340. X    "block_count blocks_free inode_count inodes_free ratio_blocks_2_inodes\n");
  341. X    
  342. X    sleep(5);
  343. X    exit(1);
  344. X}
  345. Xvoid
  346. Xterminator(x)
  347. Xint x;
  348. X{
  349. X    fprintf(stderr,"Signal caught: ichk going down on signal %d\n", x);
  350. X    exit(0);
  351. X}
  352. SHAR_EOF
  353. chmod 0444 ichk.c || echo "restore of ichk.c fails"
  354. if [ $TOUCH = can ]
  355. then
  356.     touch -am 0201040191 ichk.c
  357. fi
  358. set `wc -c ichk.c`;Wc_c=$1
  359. if test "$Wc_c" != "6095"
  360. then echo original size 6095, current size $Wc_c;fi
  361. # ============= ichk.txt ==============
  362. echo "x - extracting ichk.txt (Text)"
  363. sed 's/^X//' << 'SHAR_EOF' > ichk.txt &&
  364. X
  365. X                          Ichk - The Inode Checker.
  366. X                            Version 1.0 01/13/91
  367. X
  368. XIchk is designed to watch the condition of a file system and if specified
  369. Xbounds are exceeded, to fire off a corrective process or script.  Ichk is
  370. Xdesigned to be run from init(1) as a respawned job.  The program was originally
  371. Xwritten to address the famous SysV inode bug that typically manifests 
  372. Xitself in conjunction with news but it has many more uses.
  373. X
  374. XWhen ichk is invoked, it uses statfs(2) to collect statistics on the 
  375. Xfile system specified in the command line.  It then compares the number
  376. Xof free blocks, the number of free inodes and the ratio of free blocks
  377. Xto free inodes to specified values or defaults.  If any limits are
  378. Xexceeded, a child process is started via system(3S).  
  379. X
  380. XThe child process is passed the name of the file system and a keyword
  381. Xthat specifies the problem to be addresses.  Typical action would be in
  382. Xthe case of low inodes or increasing blocks to inodes would be to unmount
  383. Xthe affected partition and fsck it and remount it.  Typical action for
  384. Xlow blocks might be to run an emergency expire on the news partition. 
  385. X
  386. XI have observed that when the inode bug is manifesting itself, the 
  387. Xfirst indication is that as the inode count decreases rapidly, the
  388. Xratio of blocks to inodes increases.  Thus, it is possible to catch the
  389. Xproblem before the inodes run completely out and data is dropped.
  390. X
  391. XAfter any corrective action is run or if there is no problem, the daemon 
  392. Xsleeps for a designated period and then repeats the process.  Here at
  393. XDixie Communications, ichk is designated to examine things once a 
  394. Xminute.
  395. X
  396. XIchk also has an information, or "talk" mode that only reports statistics
  397. Xand then exits.  This makes ichk useful for reporting file system information
  398. Xto a corrective script and is somewhat easier and less resource intensive
  399. Xto use than df.
  400. X
  401. XIchk is equipped with sleeps of 5 seconds at all exit points which should
  402. Xkeep init happy in case something makes the program exit prematurely.
  403. XNote that if ichk is killed while a corrective process is running, ichk
  404. Xmakes no attempt to kill the child.  It is assumed that the child may
  405. Xbe  executing  actions that would be destructive if  not  run  to 
  406. Xcompletion.
  407. XTherefore if you want to kill the child process, you'll have to do it
  408. Xmanually.
  409. X
  410. XOPTIONS
  411. X
  412. XIchk has several options that may be specified at invocation.  Most options
  413. Xhave reasonable defaults.  Following are listed each of the options and
  414. Xan explanation of each.
  415. X
  416. X
  417. XUsage:
  418. X
  419. ichk <-a action> <-i inode_trig> <-r ratio> <-v> <-s sleep_secs>
  420. X  <-b block_count_trigger> <-t> file_system_name
  421. X
  422. X
  423. X-a action  Specifies the process or script to be invoked in the event a 
  424. X    limit is exceeded.  Multiple options to the child process should
  425. X    be quoted to keep the shell happy.  When the child process is invoked,
  426. X    it receives all commands specified with the -a option plus the
  427. X    name of the affected file system and a keyword that specifies the
  428. X    problem.  The keywords are:
  429. X
  430. X        ratio      = ratio of blocks to inodes exceeded.
  431. X        inode      = the low inode threshold exceeded.
  432. X        block      = the low block threshold exceeded.
  433. X    
  434. X    The default is to do nothing; ie, there is no default command 
  435. X    specified and ichk will do nothing without a specification.
  436. X
  437. X-i inode_trigger  Specifies the low inode trigger point.  When the free 
  438. X    inode count is found to fall below this point, the <action> child
  439. X    process is invoked. If -i is not specified, then the default of 200 
  440. X    inodes is used.
  441. X
  442. X-r ratio  Specifies the integer ratio of blocks to inodes above which the
  443. X    <action> child process is invoked.  The default value is 5:1.
  444. X
  445. X-s seconds  Specifies how many seconds ichk waits between checks of the
  446. X    filesystem.  The default is 10 seconds.
  447. X
  448. X-b block_count  Specifies the minimum block count below which the <action>
  449. X    child process is invoked.  The default is 1000 blocks.
  450. X
  451. X-t  Specifies the "talk mode" which reports the statistics of the file system
  452. X    and then exits.  The statistics are presented in a format easily used
  453. X    in script files.  The format is:
  454. X
  455. X     fs_name block_count blocks_free inode_count inodes_free \
  456. X    ratio_blocks_2_inodes
  457. X
  458. X-v  Specifies verbose mode.  Quite a bit of information is returned in
  459. X    verbose mode so it is suggested that it only be used for debugging 
  460. X    purposes.
  461. X
  462. Xfilesystem  Specifies the filesystem to examine.  This filesystem must
  463. X    be mounted.  The FM is somewhat vague as to how the statfs(2) call 
  464. X    works but at least with Interactive Unix, the call works correctly
  465. X    whether the actual mount point or a file on the file system is
  466. X    specified.
  467. X
  468. X
  469. XOPERATIONS
  470. X
  471. XBecause most any corrective action requires root privileges, this program
  472. Xshould be run as root.  Because it provides a tremendous opportunity for a 
  473. Xsecurity breach, the permission mask should be set as 
  474. follows:
  475. X
  476. X-r-s------   1 root     root        6644 Jan 13 13:12 /etc/ichk
  477. X
  478. Xor 04500.
  479. X
  480. XThe typical usage is for ichk to be run from init(1).  A typical inittab
  481. Xentry is as follows:
  482. X
  483. Xk2:2345:respawn:/etc/ichk -a /usr/local/news/bin/Inodes -s 60 /news >/dev/null 2>&1
  484. X
  485. XThis line uses the default values for inodes, blocks and inode to blocks ratio
  486. Xand it checks the /news filesystem every 60 seconds.  If a problem is
  487. Xfound, then the Inodes script is run.
  488. X
  489. XThe script /usr/local/news/bin/Inodes or whatever your protective program
  490. Xis named must also be owned by root and must have the permissions 0500 in
  491. Xorder to prevent a security hole.  It is also suggested that the
  492. Xdirectory that the script is in be set so that users cannot access it. 
  493. X
  494. XA copy of a typical Inodes script is included with this package.  It 
  495. Xshould examine the specified problem and take action as appropriate.
  496. X
  497. XThough most people will want to run ichk from init(1) because it makes it
  498. Xso easy to manage, there are provisions to run ichk as a true daemon.  If
  499. Xyou want to run ichk as a daemon, for instance as from /etc/rc2.d/xxx,
  500. Xsimply specify -DDAEMON on the compile line in the makefile and remake
  501. Xichk.  It will then daemonize itself when invoked. 
  502. X
  503. XOTHER USES
  504. X
  505. XThough ichk has its primary use with news, there are other uses.  For 
  506. Xexample, if you configure your system such that all log files are kept
  507. Xon a separate partition, you can have ichk monitor the free blocks on
  508. Xthe partition and fire off cleanup scripts to delete old or obese files.
  509. X
  510. XAnother use is to run ichk -t periodically against the news partition and
  511. Xdirect the output to a log file.  In this manner, you can collect use
  512. Xstatistics and in particular, monitor the block to inode ratio.   Since  
  513. Xthe needed block to inode ratio for news is typically much different
  514. Xthan that for normal file systems, you can quickly determine what 
  515. Xthe optimum ratio is.
  516. X
  517. XCOPYRIGHTS, ETC.
  518. X
  519. XThis package is copyright 1991 John De Armond, All rights reserved.  You
  520. Xmay freely copy, modify and use this program provided that if you modify
  521. Xit, you do not distribute it as ichk. If you distribute ichk, you must
  522. Xdistribute it intact with the source and documentation.    You may not
  523. Xsell it  or claim you wrote it.  I specifically disclaim any association
  524. Xwith the GNU General Public Virus, er, license.  I also specifically
  525. Xdisclaim any warranty of any kind.   
  526. X
  527. XAny feedback, errors, bugs, nicely worded gripes :-) or other comments
  528. Xwelcome.
  529. X
  530. XJohn De Armond
  531. Xjgd@dixie.com
  532. X
  533. SHAR_EOF
  534. chmod 0660 ichk.txt || echo "restore of ichk.txt fails"
  535. if [ $TOUCH = can ]
  536. then
  537.     touch -am 0201040291 ichk.txt
  538. fi
  539. set `wc -c ichk.txt`;Wc_c=$1
  540. if test "$Wc_c" != "7310"
  541. then echo original size 7310, current size $Wc_c;fi
  542. exit 0
  543. -- 
  544. John De Armond, WD4OQC        | "Purveyors of speed to the Trade"  (tm)
  545. Rapid Deployment System, Inc. |  Home of the Nidgets (tm)
  546. Marietta, Ga                  | 
  547. {emory,uunet}!rsiatl!jgd      |"Politically InCorrect.. And damn proud of it  
  548.  
  549. exit 0 # Just in case...
  550. -- 
  551. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  552. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  553. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  554. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  555.